package com.quan.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.quan.commons.core.MyBaseServiceImpl;
import com.quan.commons.utils.PageUtils;
import com.quan.system.commons.vo.SysMenuVo;
import com.quan.system.entity.SysMenu;
import com.quan.system.mapper.SysMenuMapper;
import com.quan.system.service.SysMenuService;
import com.quan.system.service.SysPermissionService;
import com.quan.system.service.SysRolePermissionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;


@Slf4j
@Service
public class SysMenuServiceImpl extends MyBaseServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    private SysMenuMapper mapper;

    @Autowired
    private SysRolePermissionService sysRolePermissionService;

    @Autowired
    private SysPermissionService sysPermissionService;

    @Override
    public SysMenuVo getInfo(Long id) {
        final SysMenu depart = super.getById(id);

        SysMenuVo bean = new SysMenuVo();
        BeanUtils.copyProperties(depart, bean);

        // 反推获取节点的父路径
        bean.setCascaderMenuPathVals(this.findPath(bean.getId()));

        return bean;
    }

    public boolean deleteByIds(Collection<? extends Serializable> idList) {
        for (Serializable id : idList) {
            this.recursiveDelete(id);
        }
        return true;
    }

    @Override
    public boolean removeById(Serializable id) {
        return this.recursiveDelete(id);
    }

    private boolean recursiveDelete(Serializable id) {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<SysMenu>();
        queryWrapper.eq("pid", id);

        List<SysMenu> child = super.list(queryWrapper);
        if (null != child) {
            for (SysMenu entity : child) {
                // 删除菜单权限
                this.sysPermissionService.deleteByMenuId(entity.getId());
                recursiveDelete(entity.getId());
            }
        }

        // 删除菜单权限
        this.sysPermissionService.deleteByMenuId(id);

        // 删除与角色关联的数据
        this.sysRolePermissionService.deleteByMenuId(id);

        return super.removeById(id);
    }

    @Override
    public List<SysMenuVo> queryList(PageUtils pageUtils, SysMenuVo vo) {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<SysMenu>(vo);

        List<SysMenu> list = super.list(pageUtils, queryWrapper);
        List<SysMenuVo> collect = list.stream().map(item -> {
            SysMenuVo bean = new SysMenuVo();
            BeanUtils.copyProperties(item, bean);
            return bean;
        }).collect(Collectors.toList());

        return collect;
    }

    @Override
    public PageUtils queryPage(PageUtils pageUtils, SysMenuVo vo) {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<SysMenu>(vo);

        if (StringUtils.isNotBlank(vo.getKeyword())) {
            queryWrapper.and(w -> {
                w.like("username", vo.getKeyword());
            });
        }

        final IPage<SysMenu> page = super.selectPage(pageUtils, queryWrapper);

        PageUtils ps = new PageUtils(page);

        final List<SysMenu> records = page.getRecords();

        final List<SysMenu> collect = records.stream().map((item) -> {
            SysMenuVo bean = new SysMenuVo();
            BeanUtils.copyProperties(item, bean);
            return bean;
        }).collect(Collectors.toList());

        ps.setRecords(collect);
        return ps;
    }


    @Override
    public List<SysMenuVo> listWithTree() {

        final List<SysMenu> list = super.list();

        // 获取一级分类
        final List<SysMenuVo> collect = list.stream()
                .filter(category -> category.getPid() == 0)
                .map(item -> {
                    SysMenuVo bean = new SysMenuVo();
                    BeanUtils.copyProperties(item, bean);

                    // 获取子分类
                    bean.setChildren(getChildrens(bean, list));

                    return bean;
                }).sorted((menu, menu2) -> {
                    //2、菜单的排序
                    return (menu.getSort() == null ? 0 : menu.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
                }).collect(Collectors.toList());

        return collect;
    }

    //递归查找所有菜单的子菜单
    private List<SysMenu> getChildrens(SysMenuVo root, List<SysMenu> all) {

        List<SysMenu> children = all.stream().filter(categoryEntity -> {
            return categoryEntity.getPid().equals(root.getId());
        }).map(item -> {
            SysMenuVo bean = new SysMenuVo();
            BeanUtils.copyProperties(item, bean);
            //1、找到子菜单(递归)
            bean.setChildren(getChildrens(bean, all));
            return bean;
        }).sorted((menu, menu2) -> {
            //2、菜单的排序
            return (menu.getSort() == null ? 0 : menu.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
        }).collect(Collectors.toList());

        return children;

    }

    @Override
    public List<SysMenuVo> listWithTreeOnPermission() {
        // 1、查出所有数据
        List<SysMenu> entityes = super.list();

        // 2、组装成父子的树形结构
        List<SysMenuVo> list = entityes.stream().filter((item) -> {
            // 1、找到所有一级分类
            return item.getPid() == 0;
        }).map((root) -> {
            SysMenuVo bean = new SysMenuVo();
            BeanUtils.copyProperties(root, bean);
            // 一级节点
            bean.setPermission(this.sysPermissionService.findPermissionByMenuId(root.getId()));

            // 2、找到所有子节点
            bean.setChildren(getChildrenOnPermission(bean, entityes));
            return bean;
        }).collect(Collectors.toList());

        return list;
    }

    /**
     * 递归查找所有子节点
     *
     * @param root
     * @param all
     * @return
     */
    public List<SysMenu> getChildrenOnPermission(SysMenuVo root, List<SysMenu> all) {
        List<SysMenu> children = all.stream().filter((entity) -> {
            return entity.getPid() == root.getId();
        }).map((item) -> {
            SysMenuVo bean = new SysMenuVo();
            BeanUtils.copyProperties(item, bean);
            bean.setPermission(this.sysPermissionService.findPermissionByMenuId(item.getId()));
            // 1、递归找到子节点
            bean.setChildren(getChildrenOnPermission(bean, all));
            return bean;
        }).collect(Collectors.toList());

        return children;
    }

    @Override
    public Long[] findPath(Long menuId) {

        List<Long> paths = new ArrayList<>();

        //递归查询是否还有父节点
        List<Long> parentPath = findParentPath(menuId, paths);

        //进行一个逆序排列
        Collections.reverse(parentPath);

        return (Long[]) parentPath.toArray(new Long[parentPath.size()]);
    }

    private List<Long> findParentPath(Long menuId, List<Long> paths) {
        //1、收集当前节点id
        paths.add(menuId);

        //根据当前分类id查询信息
        SysMenu menu = this.getById(menuId);
        //如果当前不是父分类
        if (menu.getPid() != 0) {
            findParentPath(menu.getPid(), paths);
        }
        return paths;
    }
}